﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;
using System.Net;
using System.Collections.Specialized;
using GroupCheer.FBGraphAPI.API;
using GroupCheer.FBGraphAPI;

namespace GroupCheer.Common
{
    public class oAuthFacebookApi
    {
        public enum Method { GET, POST };
        public const string AUTHORIZE = "https://graph.facebook.com/oauth/authorize";
        public const string ACCESS_TOKEN = "https://graph.facebook.com/oauth/access_token";
        private const string GRAPH_GET_URL = "https://graph.facebook.com/me/{0}?access_token={1}";

        //Facebook Setting:        
        //	See John Wang, Jeane Chen, Ian Jan, Shawn Van Pelt, or Charles Wang for access to developer account.
        //consumerKey:203950383005635 consumerSecret:836e5041351262ae57c89bb1bc5a8a7d
        //CALLBACK_URL:http://www.kintera.org/gadgets/facebook/statusupdate/doUpdate.aspx,this is definable.
        //public const string CALLBACK_URL = "http://www.kintera.org/gadgets/facebook/statusupdate/doUpdate.aspx";
        public const string CALLBACK_URL = "http://localhost:2899/CreateGoal.aspx";

        public const string POST_URL = "https://graph.facebook.com/{0}/feed";

        private string _consumerKey = "";
        private string _consumerSecret = "";
        private string _token = "";

        public string UserID
        {
            get { return FBUserContext.UserID; }
            set { FBUserContext.UserID = value; }
        }
        public string Name { get; set; }
        public string Link { get; set; }
        public string Email { get; set; }

        #region Properties

        //my app:GroupCheer-Zaric id is 354523954589274
        public string ConsumerKey
        {
            get
            {
                if (_consumerKey.Length == 0)
                {
                    _consumerKey = "354523954589274";

                }
                return _consumerKey;
            }
            set { _consumerKey = value; }
        }

        //my app:GroupCheer-Zaric secret is a45654dab3ff8cb967bcf2d3c5911214
        public string ConsumerSecret
        {
            get
            {
                if (_consumerSecret.Length == 0)
                {
                    _consumerSecret = "a45654dab3ff8cb967bcf2d3c5911214";
                }
                return _consumerSecret;
            }
            set { _consumerSecret = value; }
        }

        public string Token { get { return _token; } set { _token = value; } }
        private oAuthFacebookApi()
        {
        }
        private static oAuthFacebookApi obj;
        public static oAuthFacebookApi Instance
        {
            get {
                if (obj == null)
                {
                    obj = new oAuthFacebookApi();
                    return obj;
                }
                else
                {
                    return obj;
                }
            }
        }

        #endregion

        /// <summary> 
        /// Get the link to Facebook's authorization page for this application. 
        /// </summary> 
        /// <returns>The url with a valid request token, or a null string.</returns> 
        public string AuthorizationLinkGet()
        {
            return string.Format("{0}?client_id={1}&redirect_uri={2}&scope=offline_access,publish_stream,user_groups,friends_groups,read_stream", AUTHORIZE, this.ConsumerKey, HttpUtility.UrlEncode(CALLBACK_URL));
        }

        public FacebookUser GetUser()
        {

            var _target = string.Format(GRAPH_GET_URL, "", _token);
            FacebookUser user = new FacebookUser();

            using (WebClient client = new WebClient())
            {
                //client.Headers["User-Agent"] = "BLACKBAUD";

                //DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(FacebookUser));
                //user = serializer.ReadObject(client.OpenRead(_target)) as FacebookUser;
            }
            return user;
        }

        /// <summary> 
        /// Exchange the Facebook "code" for an access token. 
        /// </summary> 
        /// <param name="authToken">The oauth_token or "code" is supplied by Facebook's authorization page following the callback.</param> 
        public void AccessTokenGet(string authToken)
        {
            this.Token = authToken;
            string accessTokenUrl = string.Format("{0}?client_id={1}&redirect_uri={2}&client_secret={3}&code={4}",
            ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);

            string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);

            if (response.Length > 0)
            {
                //Store the returned access_token 
                NameValueCollection qs = HttpUtility.ParseQueryString(response);

                if (qs["access_token"] != null)
                {
                    this.Token = qs["access_token"];
                }
            }
        }

        /// <summary> 
        /// Web Request Wrapper 
        /// </summary> 
        /// <param name="method">Http Method</param> 
        /// <param name="url">Full url to the web resource</param> 
        /// <param name="postData">Data to post in querystring format</param> 
        /// <returns>The web server response.</returns> 
        public string WebRequest(Method method, string url, string postData)
        {

            HttpWebRequest webRequest = null;
            StreamWriter requestWriter = null;
            string responseData = "";

            webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
            webRequest.Method = method.ToString();
            webRequest.ServicePoint.Expect100Continue = false;
            webRequest.UserAgent = "BlackBaud";
            webRequest.Timeout = 20000;

            if (method == Method.POST)
            {
                webRequest.ContentType = "application/x-www-form-urlencoded";

                //POST the data. 
                requestWriter = new StreamWriter(webRequest.GetRequestStream());

                try
                {
                    requestWriter.Write(postData);
                }
                catch
                {
                    throw;
                }

                finally
                {
                    requestWriter.Close();
                    requestWriter = null;
                }
            }

            responseData = WebResponseGet(webRequest);
            webRequest = null;
            return responseData;
        }

        /// <summary> 
        /// Process the web response. 
        /// </summary> 
        /// <param name="webRequest">The request object.</param> 
        /// <returns>The response data.</returns> 
        public string WebResponseGet(HttpWebRequest webRequest)
        {
            StreamReader responseReader = null;
            string responseData = "";

            try
            {
                responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
                responseData = responseReader.ReadToEnd();
            }
            catch
            {
                throw;
            }
            finally
            {
                webRequest.GetResponse().GetResponseStream().Close();
                responseReader.Close();
                responseReader = null;
            }

            return responseData;
        }

        //public void UpdateStatus(string message)
        //{
        //    string url = string.Format("{0}?access_token={1}", POST_URL, _token);
        //    var json = WebRequest(oAuthFacebookApi.Method.POST, url, "message=" + HttpUtility.UrlEncode(message));
        //}

        //public void UpdateStatus(string message, string link, string caption)
        //{
        //    if (String.IsNullOrEmpty(link))
        //    {
        //        UpdateStatus(message);

        //        return;
        //    }

        //    string url = string.Format("{0}?access_token={1}", POST_URL, _token);
        //    var json = WebRequest(oAuthFacebookApi.Method.POST, url, "message=" + HttpUtility.UrlEncode(message) + "&link=" + HttpUtility.UrlEncode(link) + "&caption=" + HttpUtility.UrlEncode(caption));
        //}

        public string PostWallMessage(string message, string picture, string link, string name, string caption, string description, string source)
        {
            FBGraphAPIConfiguration.FBValidAccessToken = this._token;
            string objValue = PublishStream.PostWallMessage(message, picture, link, name, caption, description, source);
            return objValue;
        }

        public void PostComments(string message)
        {
            FBGraphAPIConfiguration.FBValidAccessToken = this._token;
            PublishStream.PostComment(message);
        }
        public string[] SearchGroup(string name)
        {
            FBGraphAPIConfiguration.FBValidAccessToken = this._token;
            FBGraphAPI.API.SearchGroupController controller = new FBGraphAPI.API.SearchGroupController();
            string groupIds = "";
            if (controller.Load(name))
            {
                do
                {
                    foreach (FBGraphAPI.API.Group page in controller.LastResult)
                    {
                        groupIds += "," + page.ID;
                    }
                }
                while (controller.GoNextPage());
            }
            if (groupIds.Length > 0)
                return groupIds.Substring(1).Split(',');
            else
                return null;
        }
    }

    public class FacebookUser
    {
        private long _id;
        private string _first_name;
        private string _last_name;
        private string _name;
        private string _birthday;

        public long id
        {
            get { return _id; }
            set { _id = value; }
        }

        public string first_name
        {
            get { return _first_name; }
            set { _first_name = value; }
        }

        public string last_name
        {
            get { return _last_name; }
            set { _last_name = value; }
        }

        public string name
        {
            get { return _name; }
            set { _name = value; }
        }

        public string birthday
        {
            get { return _birthday; }
            set { _birthday = value; }
        }
    }

    #region FacebookFeedWithAccessToken

    /// <summary>
    /// <para>Represents a class which maps to Json objects of feeds returned by Graph API call to</para>
    /// <para>https://graph.facebook.com/[username]|[userID]/feeds?[access token] </para>
    /// <para>With a valid access token</para>
    /// </summary>
    /// <remarks>
    /// Copyright: Copyright (c) 2010 Samaj Shekhar
    /// Last Update: 30-Dec-2010|05:19pm
    /// </remarks>
    [Serializable]
    public class FacebookFeedsWithAccessToken
    {
        /// <summary>
        /// Array of facebook feeds recived using access token
        /// </summary>
        public FacebookFeedWithAccessToken[] data { get; set; }

    }

    /// <summary>
    /// <para>Represents a class which maps to one single feed returned by Graph API call to</para>
    /// <para>https://graph.facebook.com/[feedID]?[access token]</para>
    /// <para>With a valid access token</para>
    /// </summary>
    /// <remarks>
    /// <para>Couldn't Inherit above class because Jaavscript serializer Raises AmbiguityMatchException for int like property</para> 
    /// </remarks>
    [Serializable]
    public class FacebookFeedWithAccessToken //: FacebookFeedWithoutToken
    {
        /// <summary>
        /// Feed id
        /// </summary>
        public string id { get; set; }

        /// <summary>
        /// Name and ID of the sending user
        /// </summary>

        /// <summary>
        /// The message
        /// </summary>
        public string message { get; set; }

        /// <summary>
        /// Link to the picture
        /// </summary>
        public Uri picture { get; set; }

        /// <summary>
        /// A link attached to the post
        /// </summary>
        public Uri link { get; set; }

        /// <summary>
        /// The name of the link
        /// </summary>
        public string name { get; set; }

        /// <summary>
        /// Caption of the link (appears beneth the link name)
        /// </summary>
        public string caption { get; set; }

        /// <summary>
        /// A description ogf the link (appears beneth the link caption)
        /// </summary>
        public string description { get; set; }

        /// <summary>
        /// A link to an icon representing the type of the post
        /// </summary>
        public Uri icon { get; set; }

        /// <summary>
        /// Type of the post like a Share, link, status, etc (Not mentioned in graph api documentation)
        /// </summary>
        public string type { get; set; }

        /// <summary>
        /// The time the post was initially created
        /// </summary>
        public DateTime created_time { get; set; }

        /// <summary>
        /// The time of the last comment on this post
        /// </summary>
        public DateTime updated_time { get; set; }

        /// <summary>
        /// A string representing which application was used to create this post.
        /// </summary>
        public string attribution { get; set; }
    }

    #endregion FacebookFeedWithAccessToken

   
}